﻿using HystereticBasic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HystereticRegularization
{
    /// <summary>
    /// 曲线正则化
    /// </summary>
    public class CurveRegularizedBasic
    {
        /// <summary>
        /// I点
        /// </summary>
        protected ForceDispBasicPair PointI { set; get; }

        /// <summary>
        /// J点
        /// </summary>
        protected ForceDispBasicPair PointJ { set; get; }

        /// <summary>
        /// 正则化参数
        /// 卸载残余变形系数
        /// </summary>
        protected double afa { set; get; }

        /// <summary>
        /// 正则化参数 拐点承载力系数
        /// </summary>
        protected double beta { set; get; }

        /// <summary>
        /// 目标耗能面积
        /// </summary>
        protected double targetEnergy { set; get; }

        /// <summary>
        /// 计算线上的点值
        /// </summary>
        /// <param name="disp"></param>
        /// <returns></returns>
        public virtual double GetForceOnTangentLine(double disp)
        {
            return 0;
        }

        /// <summary>
        /// 参数是否合法
        /// </summary>
        /// <param name="disp"></param>
        /// <returns></returns>
        public virtual bool isParamLegal()
        {
            return false;
        }

        /// <summary>
        /// 获得目标力位移曲线数据
        /// </summary>
        /// <returns></returns>
        public virtual MontForceDispObj GetTargetForceDispObj()
        {
            return new MontForceDispObj();
        }

        /// <summary>
        /// 计算包围面积
        /// </summary>
        /// <param name="preDisp"></param>
        /// <param name="curDisp"></param>
        /// <returns></returns>
        private double GetEnergy(double preDisp, double curDisp)
        {
            //获得力
            var preForce = this.GetForceOnTangentLine(preDisp);
            var curForce = this.GetForceOnTangentLine(curDisp);
            //计算能量
            return (preForce + curForce) * (curDisp - preDisp) * 0.5;
        }

        /// <summary>
        /// 计算能量误差
        /// </summary>
        /// <param name="afa"></param>
        /// <param name="beta"></param>
        /// <returns></returns>
        public double GetEnergyError(MontForceDispObj SparaseObj)
        {
            //能量误差
            var energyError = 0.0;
            //遍历数据
            for (int i = 1; i < SparaseObj.Count; i++)
            {
                //计算能量
                var curveEnergy = SparaseObj[i].GetEnergy(SparaseObj[i - 1]);
                var tsaiEnergy = this.GetEnergy(SparaseObj[i - 1].Disp, SparaseObj[i].Disp);
                //计算能量误差
                energyError += Math.Abs(curveEnergy - tsaiEnergy);
            }
            return energyError;
        }

        /// <summary>
        /// 获得目标力位移曲线数据
        /// </summary>
        /// <returns></returns>
        public MontForceDispObj GetTargetForceDispObj(double deltaDisp)
        {
            //初始化
            var obj = new MontForceDispObj();
            //计算数据点数目
            var prtNum = Math.Abs((int)((this.PointJ.Disp - this.PointI.Disp) / deltaDisp));
            //增加数据点
            for (int i = 0; i <= prtNum; i++)
            {
                var disp = this.PointI.Disp + i * deltaDisp;
                if ((disp - this.PointI.Disp) * (disp - this.PointJ.Disp) > 0)
                    disp = this.PointJ.Disp;
                var force = this.GetForceOnTangentLine((float)disp);
                obj.Add(new ForceDispBasicPair((float)disp, (float)force));
            }
            return obj;
        }

        /// <summary>
        /// 空的构造函数
        /// </summary>
        public CurveRegularizedBasic()
        {

        }

        /// <summary>
        /// 常用构造函数
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="beta"></param>
        public CurveRegularizedBasic(CureveRegularizedSOE obj, double beta)
        {
            this.PointI = obj.PointI;
            this.PointJ = obj.PointJ;
            this.targetEnergy = obj.targetEnergy;
            this.beta = beta;
        }

        /// <summary>
        /// 常用构造函数
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="beta"></param>
        public CurveRegularizedBasic(CureveRegularizedSOE obj, double afa, double beta)
        {
            this.PointI = obj.PointI;
            this.PointJ = obj.PointJ;
            this.targetEnergy = obj.targetEnergy;
            this.afa = afa;
            this.beta = beta;
        }
    }
}
